<?php

namespace app\admin\model\user;

use addons\epay\library\Service;
use app\common\model\User;
use think\Exception;
use think\Model;
use Yansongda\Pay\Pay;

class Withdraw extends Model
{


    // 表名
    protected $name = 'withdraw';

    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'int';

    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $deleteTime = false;

    // 追加属性
    protected $append = [
        'status_text',
        'settledmoney'
    ];

    public static function init()
    {
        /*self::afterInsert(function ($row) {
            $changedData = $row->getChangedData();
            if (isset($changedData['status']) && $changedData['status'] == 'agreed') {
                User::money(-$row['money'], $row['user_id'], '提现');
            }
        });
        self::beforeWrite(function ($row) {
            if (!isset($row['orderid']) || !$row['orderid']) {
                $row['orderid'] = date("YmdHis") . sprintf("%08d", $row['user_id']) . mt_rand(1000, 9999);
            }
        });*/
        /*self::afterWrite(function ($row) {
            $changedData = $row->getChangedData();
            if (isset($changedData['status'])) {
                if ($changedData['status'] == 'successed') {
                    $info = get_addon_info('epay');
                    if (!$info || !$info['state']) {
                        throw new Exception("请在插件市场安装微信支付宝整合插件并启用");
                    }
                    if ($row['settledmoney'] < 0.1) {
                        throw new Exception("最终提现金额最少0.1元");
                    }
                    if (isset($row['transactionid']) && $row['transactionid']) {
                        throw new Exception("无法进行重复提现");
                    }
                    try {
                        $order = [
                            'out_biz_no'   => $row['orderid'],
                            'product_code' => 'TRANS_ACCOUNT_NO_PWD',
                            'biz_scene'    => 'DIRECT_TRANSFER',
                            'payee_info'   => [
                                'identity'      => $row['account'],
                                'identity_type' => 'ALIPAY_LOGON_ID',
                                'name'          => $row['name'],
                            ],
                            'trans_amount' => $row['settledmoney'],
                        ];
                        $config = Service::getConfig('alipay');
                        $pay = Pay::alipay($config);
                        $result = $pay->transfer($order);
                        if ($result && isset($result['code']) && $result['code'] == 10000) {
                            \think\Db::name("withdraw")->where('id', $row['id'])->update(['transactionid' => $result['order_id'], 'transfertime' => strtotime($result['pay_date'])]);
                        } else {
                            exception('转账失败！');
                        }
                    } catch (\Exception $e) {
                        throw new Exception($e->getMessage());
                    }
                } elseif ($changedData['status'] == 'rejected') {
                    User::money($row['money'], $row['user_id'], '提现退回');
                }
            }
        });*/
        self::beforeDelete(function ($row) {
            if ($row['transactionid']) {
                throw new Exception("该记录无法删除");
            }
        });
    }

    public function getSettledmoneyAttr($value, $data)
    {
        return max(0, sprintf("%.2f", $data['money'] - $data['handingfee'] - $data['taxes']));
    }

    public function getStatusList()
    {
        return ['created' => __('Status created'), 'successed' => __('Status successed'), 'rejected' => __('Status rejected')];
    }

    public function getStatusTextAttr($value, $data)
    {
        $value = $value ?: ($data['status'] ?? '');
        $list = $this->getStatusList();
        return $list[$value] ?? '';
    }

    public function user()
    {
        return $this->belongsTo("\\app\\common\\model\\User", "user_id", "id")->setEagerlyType(0);
    }

    public static function newtixian($ids){
        try {
            $list = Withdraw::where('id','in',$ids)
                ->where('transactionid','=','')
                ->where(['status'=>'created'])
                ->select();

            $out_batch_no = date("YmdHis") . mt_rand(1000, 9999);
            $batch_name = '【哇哇来购】提现打款';
            $transfer_detail_list = [];
            $money = 0;

            foreach ($list as $k=>$v){
                $orderid = date("YmdHis") . sprintf("%08d", $v['user_id']) . mt_rand(1000, 9999);
                $user = User::where(['id'=>$v['user_id']])->find();
                $transfer_detail_list[] = [
                    'out_detail_no'=>$orderid,
                    'transfer_amount'=>intval($v['settledmoney']*100),
                    'transfer_remark'=>$batch_name,
                    'openid'=>$user['wechat_open_id'],
                ];
                $money+=$v['settledmoney'];
                \think\Db::name("withdraw")->where('id', $v['id'])
                    ->update(['orderid2'=>$orderid,'out_batch_no'=>$out_batch_no]);
            }
            $epay= get_addon_config('epay');
            $appid = $epay['wechat']['miniapp_id'];

            //$appid = \app\common\model\Config::get(['name'=>'app_id'])->value;
            $url = 'https://api.mch.weixin.qq.com/v3/transfer/batches';
            $pars = [];
            $pars['appid'] = $appid;//直连商户的appid
            $pars['out_batch_no'] = $out_batch_no;//商户系统内部的商家批次单号，要求此参数只能由数字、大小写字母组成，在商户系统内部唯一
            $pars['batch_name']   = $batch_name;//该笔批量转账的名称
            $pars['batch_remark'] = $batch_name;//转账说明，UTF8编码，最多允许32个字符
            $pars['total_amount'] =intval($money * 100);// 32265;//intval($money * 100);//转账总金额 单位为“分”
            $pars['total_num']    = count($list);//转账总笔数
            $pars['transfer_detail_list'] =  $transfer_detail_list;

            $token  = self::getToken($pars);//获取token
            $res    = self::https_request($url,json_encode($pars),$token);//发送请求
            $resArr = json_decode($res,true);

            if (array_key_exists('code',$resArr)){
                throw new Exception($resArr['message']);
            } else {

                $updateres = \think\Db::name("withdraw")->where('id','in', $ids)
                    ->update(['transactionid'=>$resArr['batch_id'],'status'=>'successed', 'transfertime' => time()]);
                return count($list);
            }
        } catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }

        //return $resArr;

    }

    public static function tixian($batch_name,$out_trade_no,$money,$openid){
        $epay= get_addon_config('epay');
        $appid = $epay['wechat']['miniapp_id'];

        //$appid = \app\common\model\Config::get(['name'=>'app_id'])->value;
        $url = 'https://api.mch.weixin.qq.com/v3/transfer/batches';
        $pars = [];
        $pars['appid'] = $appid;//直连商户的appid
        $pars['out_batch_no'] = $out_trade_no;//商户系统内部的商家批次单号，要求此参数只能由数字、大小写字母组成，在商户系统内部唯一
        $pars['batch_name']   = $batch_name;//该笔批量转账的名称
        $pars['batch_remark'] = $batch_name;//转账说明，UTF8编码，最多允许32个字符
        $pars['total_amount'] = intval($money * 100);//转账总金额 单位为“分”
        $pars['total_num']    = 1;//转账总笔数
        $pars['transfer_detail_list'][0]  = [
            'out_detail_no'=>'Dh'.$out_trade_no,
            'transfer_amount'=>$pars['total_amount'],
            'transfer_remark'=>$batch_name,
            'openid'=>$openid,
        ];//转账明细列表

        $token  = self::getToken($pars);//获取token

        $res    = self::https_request($url,json_encode($pars),$token);//发送请求
        $resArr = json_decode($res,true);

        return $resArr;

    }

    public static function https_request($url,$data = null,$token){
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, (string)$url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        //添加请求头
        $headers = [
            'Authorization:WECHATPAY2-SHA256-RSA2048 '.$token,
            'Accept: application/json',
            'Content-Type: application/json;',
            'User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
        ];
        if(!empty($headers)){
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }

    public static function getToken($pars)
    {
        // $url = 'https://api.mch.weixin.qq.com/v3/certificates';
        $url = 'https://api.mch.weixin.qq.com/v3/transfer/batches';
        $http_method = 'POST';//请求方法（GET,POST,PUT）
        $timestamp   = time();//请求时间戳
        $url_parts   = parse_url($url);//获取请求的绝对URL
        $nonce       = $timestamp.rand('10000','99999');//请求随机串
        $body        = json_encode((object)$pars);//请求报文主体
        $stream_opts = [
            "ssl" => [
                "verify_peer"=>false,
                "verify_peer_name"=>false,
            ]
        ];
        $epay= get_addon_config('epay');
        $mch_id = $epay['wechat']['mch_id'];
        $cert_path = $epay['wechat']['cert_client'];
        $key_path = $epay['wechat']['cert_key'];


        $apiclient_cert_path = ROOT_PATH.$cert_path;
        $apiclient_key_path  = ROOT_PATH.$key_path;

        $apiclient_cert_arr = openssl_x509_parse(file_get_contents($apiclient_cert_path,false, stream_context_create($stream_opts)));
        $serial_no          = $apiclient_cert_arr['serialNumberHex'];//证书序列号

        $mch_private_key    = file_get_contents($apiclient_key_path,false, stream_context_create($stream_opts));//密钥
        $merchant_id = $mch_id;//商户id
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $message = $http_method."\n".
            $canonical_url."\n".
            $timestamp."\n".
            $nonce."\n".
            $body."\n";
        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);//签名
        $schema = 'WECHATPAY2-SHA256-RSA2048';
        $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
            $merchant_id, $nonce, $timestamp, $serial_no, $sign);//微信返回token
        return $token;
    }

    public static function getDetailToken($url,$http_method,$data)
    {
        $timestamp   = time();//请求时间戳
        $url_parts   = parse_url($url);//获取请求的绝对URL
        $nonce       = $timestamp.rand('10000','99999');//请求随机串
        $body        = empty($data) ? '' : json_encode((object)$data);//请求报文主体
        $stream_opts = [
            "ssl" => [
                "verify_peer"=>false,
                "verify_peer_name"=>false,
            ]
        ];
        $epay= get_addon_config('epay');

        $cert_path = $epay['wechat']['cert_client'];
        $key_path = $epay['wechat']['cert_key'];
        $mch_id = $epay['wechat']['mch_id'];

        $apiclient_cert_path = ROOT_PATH.$cert_path;
        $apiclient_key_path  = ROOT_PATH.$key_path;

        $apiclient_cert_arr = openssl_x509_parse(file_get_contents($apiclient_cert_path,false, stream_context_create($stream_opts)));
        $serial_no          = $apiclient_cert_arr['serialNumberHex'];//证书序列号

        $mch_private_key    = file_get_contents($apiclient_key_path,false, stream_context_create($stream_opts));//密钥
        $merchant_id = $mch_id;//商户id
        $canonical_url = ($url_parts['path'] . (!empty($url_parts['query']) ? "?${url_parts['query']}" : ""));
        $message = $http_method."\n".
            $canonical_url."\n".
            $timestamp."\n".
            $nonce."\n".
            $body."\n";
        openssl_sign($message, $raw_sign, $mch_private_key, 'sha256WithRSAEncryption');
        $sign = base64_encode($raw_sign);//签名
        $schema = 'WECHATPAY2-SHA256-RSA2048';
        $token = sprintf('mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"',
            $merchant_id, $nonce, $timestamp, $serial_no, $sign);//微信返回token
        return $token;
    }

    public static function detailsQuery($id)
    {

        try {

            $detail = Withdraw::get($id);

            //请求URL out_batch_no
            //$url = 'https://api.mch.weixin.qq.com/v3/transfer/batches/batch-id/'.$detail['transactionid'];
            $url = 'https://api.mch.weixin.qq.com/v3/transfer/batches/out-batch-no/'.$detail['out_batch_no'].'/details/out-detail-no/'.$detail['orderid2'];
            //请求方式
            $http_method = 'GET';
            //请求参数
            $data = [];
            $token  = self::getDetailToken($url,$http_method,$data);//获取token

            $result = self::https_request($url,$data,$token);//发送请求
            //dump($url);
            $result_arr = json_decode($result,true);
            if ($result_arr){

                if (!array_key_exists('code',$result_arr)){
                    $withdraw_info = \think\Db::name("withdraw")->where('id', $id)->find();
                    if ($result_arr['detail_status']=='SUCCESS'){
                        \think\Db::name("withdraw")->where('id', $id)->update(['status' => 'successed', 'transfertime' => time()]);

                    } else if ($result_arr['detail_status']=='WAIT_PAY'){
                        //待确认
                        \think\Db::name("withdraw")->where('id', $id)->update(['status' => 'wait_pay']);
                    } elseif ($result_arr['detail_status']=='PROCESSING'){
                        //转账中
                        \think\Db::name("withdraw")->where('id', $id)->update(['status' => 'processing']);
                    } elseif ($result_arr['detail_status']=='FAIL'){
                        //转账失败
                        if ($withdraw_info['is_return']==0){
                            \app\common\model\User::money($withdraw_info['money'], $withdraw_info['user_id'], '提现退回');
                        }
                        \think\Db::name("withdraw")->where('id', $id)->update(['status' => 'fail','is_return'=>1]);
                    }
                }
            }


        }catch (\Exception $e) {
            throw new Exception($e->getMessage());
        }

    }
}
